/*
 * Alloy Analyzer
 * Copyright (c) 2002 Massachusetts Institute of Technology
 *
 * The Alloy Analyzer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The Alloy Analyzer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the Alloy Analyzer; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package alloy.transform;

import java.util.HashMap;
import java.util.Set;

import alloy.ast.LeafId;
import alloy.util.Dbg;

/**
 * An ADT representing a hierarchical mapping between names and
 * a unique identifier associated with that name in that scope.
 * The hierarchy is achieved through parents, which also allow
 * a name to be remapped to a different identifier.
 */

public class LeafIdMap {

    /** mapping from String names to LeafIds */
    private HashMap _nameToLeafId; // String -> LeafId

    /** parent of this, may be null */
    private LeafIdMap _parent;

    /**
     * @param parent_ parent map of this, can be null if
     *                there is no parent
     */
    public LeafIdMap(LeafIdMap parent_) {
        _nameToLeafId = new HashMap();
        _parent = parent_;
    }

    public LeafIdMap copy() {
	LeafIdMap newMap = new LeafIdMap(_parent);
	newMap._nameToLeafId = new HashMap(_nameToLeafId);
	return newMap;
    }

    public void setParent(LeafIdMap parent_) {
        _parent = parent_;
    }

    public LeafIdMap getParent() {
        return _parent;
    }
    
    /**
     * add a mapping to this
     */
    public void put(String name_, LeafId id_) {
	Dbg.chk(!_nameToLeafId.containsKey(name_));
        _nameToLeafId.put(name_, id_);
    }

    /**
     * get the leaf id of a name
     * @return the leaf id if the name is bound in this or an
     * ancestor of this; <code>null</code> otherwise
     */
    public LeafId lookupLeafId(String name_) {
        LeafId mappedTo = (LeafId)_nameToLeafId.get(name_);
        if (mappedTo == null) { // not mapped in this
            // lookup in parent if non-null
            if (_parent != null) {
                mappedTo = _parent.lookupLeafId(name_);
            }
        } 
        return mappedTo;
    }
    
    /**
     * get the strings for the names mapped by this
     * @return a set of strings representing the names mapped by this
     */
    public Set getMappedNames() {
    	return _nameToLeafId.keySet();
    }

    public String toString() {
        return _nameToLeafId.toString() + ((_parent == null) ? "" : (" -> " + _parent.toString()));
    }
}    
 
